function isArray(value) {
    return Object.prototype.toString.call(value) == "[object Array]";
}

function isFunction(value) {
    return Object.prototype.toString.call(value) == "[object Function]";
}

function isRegExp(value) {
    return Object.prototype.toString.call(value) == "[object RegExp]";
}

var isNativeJSON = window.JSON && Object.prototype.toString.call(JSON) == "[object JSON]";

// function Person(name, age, job){
//     if (this instanceof Person){
//         this.name = name;
//         this.age = age;
//         this.job = job;
//     } else {
//         return new Person(name, age, job);
//     }
// }
// var person1 = Person("Nicholas", 29, "Software Engineer");
// alert(window.name); //""
// alert(person1.name); //"Nicholas"
// var person2 = new Person("Shelby", 34, "Ergonomist");
// alert(person2.name); //"Shelby"

function Polygon(sides) {
    if (this instanceof Polygon) {
        this.sides = sides;
        this.getArea = function () {
            return 0;
        };
    } else {
        return new Polygon(sides);
    }
}

function Rectangle(width, height) {
    Polygon.call(this, 4);
    this.width = width;
    this.height = height;
    this.getArea = function () {
        return this.width * this.height;
    };
}

function RectangleTest() {
    Rectangle.prototype = new Polygon();
    var rect = new Rectangle(5, 10);
    console.log(rect.sides); //4
    console.log(rect.getArea()); //4
    console.log(rect);
}

//惰性载入函数
function createXHR() {
    if (typeof XMLHttpRequest != "undefined") {
        createXHR = function () {
            return new XMLHttpRequest();
        };
    } else if (typeof ActiveXObject != "undefined") {
        createXHR = function () {
            if (typeof arguments.callee.activeXString != "string") {
                var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                        "MSXML2.XMLHttp"],
                    i, len;
                for (i = 0, len = versions.length; i < len; i++) {
                    try {
                        new ActiveXObject(versions[i]);
                        arguments.callee.activeXString = versions[i];
                        break;
                    } catch (ex) {
                        //skip
                        console.log(ex);
                    }
                }
            }
            return new ActiveXObject(arguments.callee.activeXString);
        };
    } else {
        createXHR = function () {
            throw new Error("No XHR object available.");
        };
    }
    return createXHR();
}

function createXHRTest1() {
    //第二次调用不会执行if判断，直接返回createXHR本身
    var xhr = createXHR();
}

function createXHRTest2() {
    var createXHR = (function () {
        if (typeof XMLHttpRequest != "undefined") {
            return function () {
                return new XMLHttpRequest();
            };
        } else if (typeof ActiveXObject != "undefined") {
            return function () {
                if (typeof arguments.callee.activeXString != "string") {
                    var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                            "MSXML2.XMLHttp"],
                        i, len;
                    for (i = 0, len = versions.length; i < len; i++) {
                        try {
                            new ActiveXObject(versions[i]);
                            arguments.callee.activeXString = versions[i];
                            break;
                        } catch (ex) {
//skip
                        }
                    }
                }
                return new ActiveXObject(arguments.callee.activeXString);
            };
        } else {
            return function () {
                throw new Error("No XHR object available.");
            };
        }
    })();
}

//函数绑定
var handler = {
    message: "Event handled",
    handleClick: function (event) {
        console.log(event.target);
        alert(this.message + ":" + event.type);
    }
};

function handleClickTest() {
    var btn = document.getElementById("my-btn");
    EventUtil.addHandler(btn, "click", function (event) {
        handler.handleClick(event);
    });
}

//绑定环境
function bind(fn, context) {
    return function () {
        // 注意这里使用的arguments对象是内部函数的，而非bind()的
        return fn.apply(context, arguments);
    };
}

function bindTest() {
    var btn = document.getElementById("my-btn");
    EventUtil.addHandler(btn, "click", bind(handler.handleClick, handler));
}

function bindTest2() {
    var btn = document.getElementById("my-btn");
    EventUtil.addHandler(btn, "click", handler.handleClick.bind(handler));
}

//函数柯里化
function curry(fn) {
    var args = Array.prototype.slice.call(arguments, 1);
    console.log("args:" + args);
    return function () {
        var innerArgs = Array.prototype.slice.call(arguments);
        console.log("innerArgs:" + innerArgs);
        var finalArgs = args.concat(innerArgs);
        console.log("finalArgs:" + finalArgs);
        return fn.apply(null, finalArgs);
    };
}

function curriedAddTest() {
    function add(num1, num2) {
        return num1 + num2;
    }

    var curriedAdd = curry(add, 5);
    console.log(curriedAdd(3)); //8
    var curriedAdd2 = curry(add, 5, 12);
    console.log(curriedAdd2()); //17
}

function curryBind(fn, context) {
    var args = Array.prototype.slice.call(arguments, 2);
    return function () {
        var innerArgs = Array.prototype.slice.call(arguments);
        console.log("innerArgs:" + innerArgs);
        var finalArgs = args.concat(innerArgs);
        console.log("finalArgs:" + finalArgs);
        return fn.apply(context, finalArgs);
    };
}

var handler2 = {
    message: "Event handled",
    handleClick: function (name, event) {
        console.log(this.message + ":" + name + ":" + event.type);
    }
};

function curryBindTest1() {
    var btn = document.getElementById("my-btn");
    EventUtil.addHandler(btn, "click", curryBind(handler2.handleClick, handler2, "my-btn"));
}

function curryBindTest2() {
    var btn = document.getElementById("my-btn");
    EventUtil.addHandler(btn, "click", handler2.handleClick.bind(handler2, "my-btn"));
}

//防篡改对象
function personTest() {
    var person1 = {name: "Nicholas"};
    person1.age = 29;
    console.log(person1.age);
    console.log(Object.isExtensible(person1)); //true
    var person2 = {name: "Nicholas"};
    Object.preventExtensions(person2);
    person2.age = 29;
    console.log(person2.age); //undefined
    console.log(Object.isExtensible(person2)); //false
}

//密封对象
function sealedObjectTest() {
    var person = {name: "Nicholas"};
    console.log("isExtensible:" + Object.isExtensible(person)); //true
    console.log("isSealed:" + Object.isSealed(person)); //false
    Object.seal(person);
    console.log("isExtensible:" + Object.isExtensible(person)); //false
    console.log("isSealed:" + Object.isSealed(person)); //true

    person.age = 29;
    console.log(person.age); //undefined
    delete person.name;
    console.log(person.name); //"Nicholas"
    person.name = "Bobby";
    console.log(person.name); //"Bobby"
}

//冻结对象
function frozenObjectTest() {
    var person = {name: "Nicholas"};
    console.log(Object.isExtensible(person)); //true
    console.log(Object.isSealed(person)); //false
    console.log(Object.isFrozen(person)); //false
    Object.freeze(person);
    console.log(Object.isExtensible(person)); //false
    console.log(Object.isSealed(person)); //true
    console.log(Object.isFrozen(person)); //true

    person.age = 29;
    console.log(person.age); //undefined
    delete person.name;
    console.log(person.name); //"Nicholas"
    person.name = "Bobby";
    console.log(person.name); //"Nicholas"
}

function setTimeoutTest() {
    var btn = document.getElementById("my-btn");
    btn.onclick = function () {
        setTimeout(function () {
            document.getElementById("message").style.visibility = "visible";
        }, 250);
        //其他代码
    };
}

function linkTimeoutTest() {
    var left = 0;
    var direction = 1;
    setTimeout(function () {
        var div = document.getElementById("myDiv");
        left = parseInt(div.style.marginLeft) + 5 * direction;
        div.style.marginLeft = left + "px";
        if (left < 200 && left > 0) {
            setTimeout(arguments.callee, 50);
        } else {
            direction *= -1;
            setTimeout(arguments.callee, 50);
        }
    }, 50);
}

function chunk(array, process, context) {
    setTimeout(function () {
        var item = array.shift();
        process.call(context, item);
        if (array.length > 0) {
            setTimeout(arguments.callee, 100);
        }
    }, 100);
}

function chunkTest() {
    var data = [12, 123, 1234, 453, 436, 23, 23, 5, 4123, 45, 346, 5634, 2234, 345, 342];

    function printValue(item) {
        var div = document.getElementById("chunkDiv");
        div.innerHTML += item + "<br>";
    }

    chunk(data, printValue);
}

function processorTest() {
    var processor = {
        timeoutId: null,
        //实际进行处理的方法
        performProcessing: function () {
            //实际执行的代码
        },
        //初始处理调用的方法
        process: function () {
            clearTimeout(this.timeoutId);
            var that = this;
            this.timeoutId = setTimeout(function () {
                that.performProcessing();
            }, 100);
        }
    };
    //尝试开始执行
    processor.process();
}

function throttle(method, context) {
    clearTimeout(method.tId);
    method.tId = setTimeout(function () {
        method.call(context);
    }, 100);
}


function resizeDiv() {
    var div = document.getElementById("resizeDiv");
    div.style.height = div.offsetWidth + "px";
}

function onresizeTest() {
    window.onresize = function () {
        throttle(resizeDiv);
    };
}


function EventTarget() {
    this.handlers = {};
}

EventTarget.prototype = {
    constructor: EventTarget,
    addHandler: function (type, handler) {
        if (typeof this.handlers[type] == "undefined") {
            this.handlers[type] = [];
        }
        this.handlers[type].push(handler);
    },
    fire: function (event) {
        if (!event.target) {
            event.target = this;
        }
        if (this.handlers[event.type] instanceof Array) {
            var handlers = this.handlers[event.type];
            for (var i = 0, len = handlers.length; i < len; i++) {
                handlers[i](event);
            }
        }
    },
    removeHandler: function (type, handler) {
        if (this.handlers[type] instanceof Array) {
            var handlers = this.handlers[type];
            for (var i = 0, len = handlers.length; i < len; i++) {
                if (handlers[i] === handler) {
                    break;
                }
            }
            handlers.splice(i, 1);
        }
    }
};

function EventTargetTest() {
    function handleMessage(event) {
        alert("Message received: " + event.message);
    }

    //创建一个新对象
    var target = new EventTarget();
    //添加一个事件处理程序
    target.addHandler("message", handleMessage);
    //触发事件
    target.fire({type: "message", message: "Hello world!"});
    //删除事件处理程序
    target.removeHandler("message", handleMessage);
    //再次，应没有处理程序
    target.fire({type: "message", message: "Hello world!"});
}

// function Person(name, age) {
//     EventTarget.call(this);
//     this.name = name;
//     this.age = age;
// }
//
// inheritPrototype(Person, EventTarget);
// Person.prototype.say = function (message) {
//     this.fire({type: "message", message: message});
// };
function mousemoveTest() {
    EventUtil.addHandler(document, "mousemove", function (event) {
        var myDiv = document.getElementById("myDropDiv");
        myDiv.style.left = event.clientX + "px";
        myDiv.style.top = event.clientY + "px";
    });
}


var DragDrop = function () {
    var dragdrop = new EventTarget(),
        dragging = null,
        diffX = 0,
        diffY = 0;

    function handleEvent(event) {
        //获取事件和目标
        event = EventUtil.getEvent(event);
        var target = EventUtil.getTarget(event);
        //确定事件类型
        switch (event.type) {
            case "mousedown":
                if (target.className.indexOf("draggable") > -1) {
                    dragging = target;
                    diffX = event.clientX - target.offsetLeft;
                    diffY = event.clientY - target.offsetTop;
                    dragdrop.fire({
                        type: "dragstart", target: dragging,
                        x: event.clientX, y: event.clientY
                    });
                }
                break;
            case "mousemove":
                if (dragging !== null) {
                    //指定位置
                    dragging.style.left = event.clientX + "px";
                    dragging.style.top = event.clientY + "px";
                    //触发自定义事件
                    dragdrop.fire({
                        type: "drag", target: dragging,
                        x: event.clientX, y: event.clientY
                    });
                }
                break;
            case "mouseup":
                dragdrop.fire({
                    type: "dragend", target: dragging,
                    x: event.clientX, y: event.clientY
                });
                dragging = null;
                break;
        }
    };
    //公共接口
    dragdrop.enable = function () {
        EventUtil.addHandler(document, "mousedown", handleEvent);
        EventUtil.addHandler(document, "mousemove", handleEvent);
        EventUtil.addHandler(document, "mouseup", handleEvent);
    };
    dragdrop.disable = function () {
        EventUtil.removeHandler(document, "mousedown", handleEvent);
        EventUtil.removeHandler(document, "mousemove", handleEvent);
        EventUtil.removeHandler(document, "mouseup", handleEvent);
    };
    return dragdrop;
}();

